import java.util.LinkedList;
import java.util.Queue;

class MyBlockingQueue<E> {
	int capacity = 0;

	public MyBlockingQueue(int capacity) {
		this.capacity = capacity;
	}

	private Queue<E> queue = new LinkedList<E>();

	/**
	 * Make a blocking Dequeue call so that we'll only return when the queue has
	 * something on it, otherwise we'll wait until something is put on it.
	 * 
	 * @returns This will return null if the thread wait() call is interrupted.
	 */
	public int size() {
		return queue.size();
	}

	public synchronized E dequeue() throws InterruptedException {
		E msg = null;
		while (queue.isEmpty()) {
			try {
				wait();
			} catch (InterruptedException e) {

				throw e;
			}
		}
		msg = queue.remove();
		notifyAll();
		return msg;
	}

	/**
	 * Enqueue will add an object to this queue, and will notify any waiting
	 * threads that there is an object available.
	 */
	public synchronized void enqueue(E o) {
		if (queue.size() == capacity) {
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		queue.add(o);
		notifyAll();
	}
}

class ProducerConsumerMyBQueue {
	public static void main(String args[]) {
		MyBlockingQueue<Integer> bQueue = new MyBlockingQueue<Integer>(10);
		Thread t1 = new Producer(bQueue);
		Thread t2 = new Consumer(bQueue);
		t1.start();
		t2.start();

	}
}

class Consumer extends Thread {
	// This will be assigned in the constructor
	private MyBlockingQueue<Integer> queue = null;

	Consumer(MyBlockingQueue<Integer> q) {
		this.queue = q;
	}

	public void run() {
		while (true) {
			int i = 0;
			try {
				i = queue.dequeue();
				System.out.println("consumer consumed : " + i);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
	}
}

class Producer extends Thread {
	// This will be assigned in the constructor
	private MyBlockingQueue<Integer> queue = null;

	Producer(MyBlockingQueue<Integer> q) {
		this.queue = q;
	}

	public void run() {
		for (int i = 0; i < 20; i++) {
			try {
				System.out.println("Producer Produced: " + i);
				queue.enqueue(i);
				System.out.println("q size : " + queue.size());
			} catch (Exception ex) {
			}
		}
	}

}